/* Copyright 2008 Bas van den Berg
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef MUDOBJECT_H
#define MUDOBJECT_H

#include <string>
#include <list>
#include <vector>

namespace Chronos {

class CmdVisitor;
class Room;
class MudObject;
class MudMobile;
class MudPlayer;
class MudObjectTriggerAction;

enum MudObjectEvent { OBJECT_DESTRUCTION=0,
                      MUDMOBILE_DEATH,
                      MUDITEM_PICKUP,
                      MUDMOBILE_MOVEMENT,
                      MUDPLAYER_LOGOUT,
                      MUDMOBILE_START_COMBAT
                    };

enum RoomEvent { MUDMOBILE_ARRIVE=0 };

enum MudObjectTrigger { MUDEXIT_PASS=0,
                        MUDITEM_TRY_PICKUP,
                        MUDOPENABLE_TRY_OPEN,
                        MUDCONTAINER_TRY_ACCESS
                      };

enum MudTriggerAction { MESSAGE=0, ATTACK };

class MudObjectListener {
public:
    virtual ~MudObjectListener() {}

    // NOTE: return value false means remove listener from list.
    // When notified, a listener is not allowed to do calls on the object anymore
    virtual bool handleObjectEvent(MudObject& object, MudObjectEvent event) = 0;
};


class MudObject {
public:
    MudObject(const std::string& name_, const std::string& descr_);
    MudObject(const MudObject& rhs);
    virtual ~MudObject();
    static unsigned int count;

	void addAlias(const std::string& alias);
	bool matchesName(const std::string& callName) const;

    const std::string& getName() const;
    virtual const std::string& getDescription() const;
    bool isVisible() const;
    void setVisible(bool v);
    void setRoom(Room* newRoom);
    Room* getRoom() const;
    bool isRoomListener() const;

    virtual void accept(CmdVisitor& v);
    // NOTE: return value false means remove listener from list.
    // When notified, a listener is not allowed to do calls on the object anymore
    virtual bool handleRoomEvent(MudMobile&, RoomEvent) { return true; }

    void addListener(MudObjectListener& listener);
    void removeListener(MudObjectListener& listener);
    virtual void generateEvent(MudObjectEvent event);

    virtual void handleTrigger(MudTriggerAction, MudMobile*, const std::string&) {}
    void addTrigger(MudObjectTrigger trigger, const std::string& listener, bool blocks, MudTriggerAction action, const std::string& msg);
protected:
    bool activateTrigger(MudObjectTrigger trigger, MudMobile* cause);
	void clearTrigger(MudObjectTrigger trigger);
    
    std::string name;
    std::string descr;
    bool visible;
    Room* room;
private:    
    typedef std::list<MudObjectListener*> Listeners;
    typedef Listeners::iterator ListenersIter;
    Listeners listeners;

    typedef std::list<MudObjectTriggerAction*> TriggerActions;
    typedef TriggerActions::const_iterator TriggerActionsConstIter;
    typedef TriggerActions::iterator TriggerActionsIter;
    TriggerActions triggers;

	typedef std::vector<std::string> Aliases;
	typedef Aliases::const_iterator AliasesIter;
	Aliases aliases;

    MudObject& operator= (const MudObject&);
};

}

#endif

